package com.fivefu.core.skyeye.event.services.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fivefu.base.common.utils.date.DateUtils;
import com.fivefu.core.skyeye.event.entity.*;
import com.fivefu.base.common.utils.str.StrUtils;
import com.fivefu.core.skyeye.event.mapper.DbAiSceneCameraMapper;
import com.fivefu.core.skyeye.event.services.*;
import com.fivefu.core.skyeye.event.vo.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;

import static java.util.stream.Collectors.toList;

/**
 * <p>
 * 探头场景关联表 服务实现类
 * </p>
 *
 * @author 
 * @since 2022-07-15 13:53:19
 */
@Service
public class DbAiSceneCameraServiceImpl extends ServiceImpl<DbAiSceneCameraMapper, DbAiSceneCamera> implements DbAiSceneCameraService {

    @Resource
    private DbAiSceneCameraImageService dbAiSceneCameraImageService;

    /**
     * 通过场景唯一标识和探头唯一标识查询关联信息
     * @param sceneId 场景唯一标识
     * @param cameraId 探头唯一标识
     * @return
     */
    @Override
    public DbAiSceneCamera querySceneCamera(String sceneId, String cameraId){
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("scene_id",sceneId);
        wrapper.eq("camera_id",cameraId);
        wrapper.orderByDesc("created_time");
        List<DbAiSceneCamera> dbAiSceneCameras = baseMapper.selectList(wrapper);
        return dbAiSceneCameras.get(0);
    }

    /**
     * 通过场景唯一标识和探头唯一标识查询未删除的关联信息
     * @param sceneId 场景唯一标识
     * @param cameraId 探头唯一标识
     * @return
     */
    @Override
    public DbAiSceneCamera getSceneCamera(String sceneId, String cameraId){
        List<DbAiSceneCamera> list = querySceneCameraList(sceneId, cameraId);
        if (list != null && !list.isEmpty()){
            return list.get(0);
        }
        return null;
    }
    /**
     * 查询场景探头关联信息
     * @param sceneCamera
     * @return
     */
    @Override
    public Map<String, Object> formatSceneCamera(DbAiSceneCamera sceneCamera){
        Map<String,Object> map = JSON.parseObject(JSON.toJSONString(sceneCamera, SerializerFeature.WriteMapNullValue), Map.class);
        //是否开启
        if (sceneCamera.getEnable() != null){
            if (sceneCamera.getEnable().equals(1)){
                map.put("enableCN","是");
            }else {
                map.put("enableCN","否");
            }
        }
        //是否限定区域
        if (sceneCamera.getScope() != null){
            if (sceneCamera.getScope().equals(1)){
                map.put("scopeCN","是");
            }else {
                map.put("scopeCN","否");
            }
        }
        if (sceneCamera.getCreatedTime() != null){
            String time = DateUtils.format(sceneCamera.getCreatedTime(),DateUtils.DEFAULT_DATETIME_PATTERN);
            map.put("createdTime", time);
        }
        if (sceneCamera.getUpdatedTime() != null){
            String time = DateUtils.format(sceneCamera.getUpdatedTime(),DateUtils.DEFAULT_DATETIME_PATTERN);
            map.put("updatedTime", time);
        }
        return map;
    }

    /**
     * 分页获取场景探头列表
     * @param cameraCode 场景唯一标识
     * @param page
     * @param limit
     * @return
     */
    @Override
    public Page<DbAiSceneCamera> querySceneCameraByPage(String cameraCode, Integer page, Integer limit) {
        Page<DbAiSceneCamera> backPage = new Page<>();
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        wrapper.eq("scene_id",cameraCode);
        if (page != null && limit != null){
            Page<DbAiSceneCamera> iPage = new Page<>(page,limit);
            backPage = baseMapper.selectPage(iPage,wrapper);
        }else {
            List<DbAiSceneCamera> list = baseMapper.selectList(wrapper);
            backPage.setTotal(list.size());
            backPage.setRecords(list);
        }

        return backPage;
    }

    /**
     * 编辑场景探头
     * @param sceneCamera 场景探头信息
     * @param userid 操作用户编号
     * @return
     */
    @Override
    public boolean editSceneCamera(DbAiSceneCamera sceneCamera, String userid){
        LocalDateTime time = LocalDateTime.now();
        sceneCamera.setUpdatedBy(userid);
        sceneCamera.setUpdatedTime(time);

        DbAiSceneCamera oldScene = getSceneCamera(sceneCamera.getSceneId(), sceneCamera.getCameraId());
        if (oldScene != null){
            //修改
            sceneCamera.setId(oldScene.getId());
            baseMapper.updateById(sceneCamera);

            //缩略图
            if (StrUtils.isNotNull(sceneCamera.getImage())){
                dbAiSceneCameraImageService.addSceneCameraImage(userid,sceneCamera.getId() + "",sceneCamera.getScope(),sceneCamera.getScopeArea(),sceneCamera.getImage());
            }

            //判断
            boolean enable = sceneCamera.getEnable().equals(oldScene.getEnable());//是否开启有没有发生改变
            boolean scope = sceneCamera.getScope().equals(oldScene.getScope());//是否限定区域有没有发生改变
            boolean scopeArea = sceneCamera.getScopeArea().equals(oldScene.getScopeArea());//区域是否发生改变
            boolean cameraValidTime = sceneCamera.getCameraValidTime().equals(oldScene.getCameraValidTime());//探头有效时间是否发生改变
            boolean cvParam = sceneCamera.getCvParam().equals(oldScene.getCvParam());//识别参数是否发生改变
            boolean eventNode = sceneCamera.getEventNode().equals(oldScene.getEventNode());//识别机器编号是否发生改变
            if (!enable || !scope || !scopeArea || !cameraValidTime || !cvParam || !eventNode){
                return true;
            }
        }else{
            //新增
            sceneCamera.setCreatedBy(userid);
            sceneCamera.setCreatedTime(LocalDateTime.now());
            sceneCamera.setIsDelete(0);
            baseMapper.insert(sceneCamera);

            //缩略图
            if (StrUtils.isNotNull(sceneCamera.getImage())){
                dbAiSceneCameraImageService.addSceneCameraImage(userid,sceneCamera.getId() + "",sceneCamera.getScope(),sceneCamera.getScopeArea(),sceneCamera.getImage());
            }

            //判断
            if (sceneCamera.getEnable().equals(1)){
                return true;
            }
        }
        return false;
    }

    /**
     * 能否进行编辑场景探头
     * @param sceneCamera 场景探头信息
     * @param sliceMaxNum 切片最大值
     * @param eventMaxNum 识别节点最大值
     * @return
     */
    public boolean isEditSceneCamera(DbAiSceneCamera sceneCamera,Integer sliceMaxNum,Integer eventMaxNum){
        DbAiSceneCamera oldScene = getSceneCamera(sceneCamera.getSceneId(), sceneCamera.getCameraId());
        if (oldScene != null){
            boolean event = sceneCamera.getEventNode().equals(oldScene.getEventNode());//识别机器编号是否发生改变
            if (! event){//发生改变
                boolean eventNodeCountMax = isEventNodeCountMax(sceneCamera.getEventNode(), eventMaxNum);
                if (! eventNodeCountMax){
                     return true;
                }
            }else {
                return true;
            }
        }else {
            boolean sliceNodeCountMax = isSliceNodeCountMax(sceneCamera.getSliceNode(), sliceMaxNum);
            boolean eventNodeCountMax = isEventNodeCountMax(sceneCamera.getEventNode(), eventMaxNum);
            if (! sliceNodeCountMax && !eventNodeCountMax){
                return true;
            }
        }
        return false;
    }

    /**
     * 有没有达到切片机器最大值
     * @param sliceNode 切片节点编号
     * @param sliceMaxNum 切片最大值
     * @return
     */
    public boolean isSliceNodeCountMax(Long sliceNode,Integer sliceMaxNum){
        List<Map<String, Object>> sliceNodeCountList = baseMapper.getSliceNodeCount();//已存在的切片编号和切片数量
        for (Map<String, Object> map : sliceNodeCountList) {
            Long slice = Long.valueOf(map.get("sliceNode").toString());
            if (slice.equals(sliceNode)){
                Integer sliceNum = Integer.valueOf(map.get("sliceNodeNum").toString());
                if (sliceNum.equals(sliceMaxNum)){
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 有没有达到识别机器最大值
     * @param eventNode 识别节点编号
     * @param eventMaxNum 识别最大值
     * @return
     */
    public boolean isEventNodeCountMax(Long eventNode,Integer eventMaxNum){
        List<Map<String, Object>> eventNodeCountList = baseMapper.getEventNodeCount();//已存在的识别机器数量信息
        for (Map<String, Object> map : eventNodeCountList) {
            Long event = Long.valueOf(map.get("eventNode").toString());
            if (event.equals(eventNode)){
                Integer eventNum = Integer.valueOf(map.get("eventNodeNum").toString());
                if (eventNum.equals(eventMaxNum)){
                    return true;
                }
            }
        }
        return false;
    }
    /**
     * 开启、关闭场景探头
     * @param id 场景探头编号
     * @param userid 用户编号
     * @param enable 是否启用(0:否 1:启用)
     * @return
     */
    @Override
    public void enableSceneCamera(Long id, String userid, Integer enable) {
        //修改
        DbAiSceneCamera sceneCamera = new DbAiSceneCamera();
        sceneCamera.setUpdatedBy(userid);
        sceneCamera.setUpdatedTime(LocalDateTime.now());
        sceneCamera.setEnable(enable);//是否开启
        sceneCamera.setId(id);
        baseMapper.updateById(sceneCamera);
    }

    /**
     * 删除场景探头
     * @param id 场景探头编号
     * @param userid 用户编号
     */
    @Override
    public void deleteSceneCamera(Long id,String userid){
        //修改
        DbAiSceneCamera sceneCamera = new DbAiSceneCamera();
        sceneCamera.setUpdatedBy(userid);
        sceneCamera.setUpdatedTime(LocalDateTime.now());
        sceneCamera.setIsDelete(1);//是否删除
        sceneCamera.setEnable(0);//关闭
        sceneCamera.setId(id);
        baseMapper.updateById(sceneCamera);
    }

    /**
     * 通过编号查询场景探头信息
     * @param id 场景探头编号
     * @return
     */
    @Override
    public DbAiSceneCamera querySceneCameraByID(Long id){
        DbAiSceneCamera dbAiSceneCamera = baseMapper.selectById(id);
        return dbAiSceneCamera;
    }

    /**
     * 根据开启的场景标识查询开启的探头集
     * @param sceneCodeList 场景编号集合
     * @param sliceCodeList 切片机器集合
     * @return
     */
    public List<DbAiSceneCamera> getOpenCamera(List<String> sceneCodeList, List<String> sliceCodeList) {
        List<UrlChannelVo> allCameraUrl = new ArrayList<>();
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        wrapper.eq("enable",1);
        wrapper.in("scene_id",sceneCodeList);
        wrapper.in("slice_node",sliceCodeList);
        List<DbAiSceneCamera> resultList = baseMapper.selectList(wrapper);
        return resultList;
    }

    /**
     * 通过场景标识查询场景下探头编号集合
     * @param sceneCode 场景标识
     * @param enable 是否开启;0:否,1:是
     * @return
     */
    @Override
    public List<String> queryCameraCodeBySceneID(String sceneCode, Integer enable){
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        wrapper.eq("scene_id",sceneCode);
        if (enable != null){
            wrapper.eq("enable",enable);
        }
        wrapper.select("camera_id");
        List<DbAiSceneCamera> list = baseMapper.selectList(wrapper);
        List<String> codeList = list.stream().map(k -> k.getCameraId()).collect(toList());
        return codeList;
    }

    /**
     * 查询场景下的开启探头
     * @param sceneList 场景唯一标识
     * @return
     */
    @Override
    public List<String> getCamera(List<String> sceneList) {
        List<String> camera = baseMapper.getCamera(sceneList);
        return camera;
    }

    /**
     * 查询切片机器数量信息
     * @return
     */
    @Override
    public List<Map<String,Object>> querySliceNodeCount() {
        List<Map<String,Object>> sliceNodeList = baseMapper.getSliceNodeCount();
        return sliceNodeList;
    }

    /**
     * 查询识别机器数量信息
     * @return
     */
    @Override
    public List<Map<String,Object>> queryEventNodeCount() {
        List<Map<String,Object>> eventNodeList = baseMapper.getEventNodeCount();
        return eventNodeList;
    }

    /**
     * 查询已使用切片的数量
     * @param sliceId 切片编号
     * @return
     */
    @Override
    public Integer querySliceNodeNum(Long sliceId) {
        Integer sliceNum = baseMapper.getSliceNodeNum(sliceId);
        if (sliceNum == null){
            return 0;
        }else {
            return sliceNum;
        }
    }

    /**
     * 查询已使用识别的数量
     * @param eventId 识别编号
     * @return
     */
    @Override
    public Integer queryEventNodeNum(Long eventId) {
        Integer eventNum = baseMapper.getEventNodeNum(eventId);
        if (eventNum == null){
            return 0;
        }else {
            return eventNum;
        }
    }

    /**
     * 查询未删除的场景探头
     * @return
     */
    @Override
    public List<DbAiSceneCamera> querySceneCameras() {
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        List<DbAiSceneCamera> dbAiSceneCameras = baseMapper.selectList(wrapper);
        return dbAiSceneCameras;
    }

    /**
     * 根据探头标识查询切片节点编号
     * @param cameraCode 探头唯一标识
     * @return
     */
    @Override
    public DbAiSceneCamera querySliceNodeByCamera(String cameraCode) {
        List<DbAiSceneCamera> dbAiSceneCameras = querySceneCameraList(null, cameraCode);
        DbAiSceneCamera dbAiSceneCamera = null;
        if (dbAiSceneCameras != null && dbAiSceneCameras.size() >0){
            dbAiSceneCamera = dbAiSceneCameras.get(0);
        }
        return dbAiSceneCamera;
    }

    /**
     * 通过场景唯一标识获取场景探头关联集合
     * @param sceneIds 场景唯一标识集合
     * @return
     */
    @Override
    public List<DbAiSceneCamera> querySceneCameraList(List<String> sceneIds){
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        if (sceneIds != null && sceneIds.size() > 0) {
            wrapper.in("scene_id", sceneIds);
        }
        wrapper.orderByDesc("created_time");
        List<DbAiSceneCamera> list = baseMapper.selectList(wrapper);
        return list;
    }

    /**
     * 通过场景唯一标识或探头唯一标识查询关联信息
     * @param sceneId 场景唯一标识
     * @param cameraId 探头唯一标识
     * @return
     */
    @Override
    public List<DbAiSceneCamera> querySceneCameraList(String sceneId, String cameraId){
        QueryWrapper<DbAiSceneCamera> wrapper = new QueryWrapper<>();
        wrapper.eq("is_delete",0);
        if (StrUtils.isNotNull(sceneId)) {
            wrapper.eq("scene_id", sceneId);
        }
        if (StrUtils.isNotNull(cameraId)) {
            wrapper.eq("camera_id", cameraId);
        }
        wrapper.orderByDesc("created_time");
        List<DbAiSceneCamera> list = baseMapper.selectList(wrapper);
        return list;
    }
}
